﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Research.Kinect.Nui;

namespace Kinductor.Gestures
{
    class GazeDetector
    {
        #region Fields

        Runtime nui;
        #endregion

        #region Properties

        public SkeletonData Skeleton { get; set; }
        public double GazeX { get; set; }
        public double GazeY { get; set; }
        public double GazeZ { get; set; }
        BeatPatternRecognizer beatPattern;
        HandConductingStatus rightHandStatus, leftHandStatus;
        HandConductingPhase rightHandPhase, leftHandPhase;

        #endregion

        #region Events

        #region GazeDetectorUpdated

        public event EventHandler GazeDetectorUpdated;

        protected void OnGazeDetectorUpdated()
        {
            if (GazeDetectorUpdated == null)
                return;
            GazeDetectorUpdated(this, EventArgs.Empty);
        }
        #endregion

        #endregion

        #region Constructors

        public GazeDetector(Runtime kinectRuntime, BeatPatternRecognizer beatPattern)
        {
            if (kinectRuntime == null)
                throw new ArgumentNullException("kinectRuntime");

            this.nui = kinectRuntime;
            this.beatPattern = beatPattern;

            nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
        }

        #endregion

        #region Private Methods

        void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            SkeletonFrame allSkeletons = e.SkeletonFrame;

            //get the first tracked skeleton
            Skeleton = (from s in allSkeletons.Skeletons
                        where s.TrackingState == SkeletonTrackingState.Tracked &&
                              s.Joints[JointID.Head].TrackingState == JointTrackingState.Tracked
                        select s).OrderBy((s) => s.Joints[JointID.Head].Position.Z * Math.Abs(s.Joints[JointID.Head].Position.X))
                                 .FirstOrDefault();
            if (Skeleton == null)
                return;

            Joint head = Skeleton.Joints[JointID.Head];
            Joint shoulderCenter = Skeleton.Joints[JointID.ShoulderCenter];
            Joint shoulderLeft = Skeleton.Joints[JointID.ShoulderLeft];
            Joint shoulderRight = Skeleton.Joints[JointID.ShoulderRight];

            getGazeXCoordinate(head, shoulderCenter, shoulderLeft, shoulderRight);
            getGazeYCoordinate();

            OnGazeDetectorUpdated();
            
        }

        void getGazeXCoordinate(Joint head, Joint shoulderCenter, Joint shoulderLeft, Joint shoulderRight)
        {
            //here do magic of calculation
            //get x,y of gaze
            GazeX = head.Position.X;
        }

        void getGazeZCoordinate(Joint head)
        {
            GazeZ = head.Position.Z;
        }

        void getGazeYCoordinate()
        {
            rightHandStatus = beatPattern.rightHandStatus;
            leftHandStatus = beatPattern.leftHandStatus;
            rightHandPhase = rightHandStatus.Phase;
            leftHandPhase = leftHandStatus.Phase;

            if (rightHandPhase == HandConductingPhase.NotConducting && leftHandPhase == HandConductingPhase.NotConducting)
            {
                //invalid, no gaze y value
                GazeY = -1;
            }
            else if (rightHandPhase == HandConductingPhase.MarkingTime && leftHandPhase == HandConductingPhase.MarkingTime)
            {
                //average of ictus
                GazeY = (rightHandStatus.LastIctusPosition.Y + leftHandStatus.LastIctusPosition.Y)/2.0;
            }
            else if (rightHandPhase == HandConductingPhase.Steady && leftHandPhase == HandConductingPhase.Steady)
            {
                GazeY = (rightHandStatus.LastWristPosition.Y + leftHandStatus.LastWristPosition.Y)/2.0;
            }
            else if (rightHandPhase == HandConductingPhase.Steady && (leftHandPhase == HandConductingPhase.NotConducting || leftHandPhase == HandConductingPhase.MarkingTime))
            {
                GazeY = rightHandStatus.LastWristPosition.Y;
            }
            else if ((rightHandPhase == HandConductingPhase.NotConducting || rightHandPhase == HandConductingPhase.MarkingTime) && leftHandPhase == HandConductingPhase.Steady)
            {
                GazeY = leftHandStatus.LastWristPosition.Y;
            }
            else if (rightHandPhase == HandConductingPhase.NotConducting && leftHandPhase == HandConductingPhase.MarkingTime)
            {
                GazeY = leftHandStatus.LastIctusPosition.Y;
            }
            else if (rightHandPhase == HandConductingPhase.MarkingTime && leftHandPhase == HandConductingPhase.NotConducting)
            {
                GazeY = rightHandStatus.LastIctusPosition.Y;
            }

        }

        #endregion

    }
}
